/*********************************************************************
 *  ports:
 *  VL_IN8(&clk,0,0);
 *  VL_IN8(&rstn,0,0);
 *  VL_IN8(&dut->set_alarm,0,0);
 *  VL_IN8(&dut->set_hour,0,0);
 *  VL_IN8(&dut->set_min,0,0);
 *  VL_OUT8(&hour,7,0);
 *  VL_OUT8(&min,7,0);
 *  VL_OUT8(&sec,7,0);
**********************************************************************/

#include <stdlib.h>
#include <iostream>
#include <verilated.h>
#include <verilated_vcd_c.h>
#include "ValarmTop.h"
#include "ValarmTop___024root.h"

#define PERIOD 4
#define MAX_TIME 3000

uint64_t sim_time = 0;

void reset(ValarmTop*, int);
void pos_edge_eval(ValarmTop*);
void neg_edge_eval(ValarmTop*);

int main(int argc, char **argv) {
  ValarmTop* dut = new ValarmTop;

	Verilated::traceEverOn(true);
	VerilatedVcdC *m_trace = new VerilatedVcdC;
	dut->trace(m_trace, 2);
	m_trace->open("waveform.vcd");

  dut->set_min = 0;
  dut->set_hour = 0;

  while(sim_time < MAX_TIME) {
    reset(dut, int(1.5*PERIOD));

    if(sim_time < 70*PERIOD) {
      dut->set_alarm = 0;
    } else {
      dut->set_alarm = 1;
    }

    if(sim_time < 200*PERIOD) {
      dut->set_min = 1;
    } else {
      dut->set_min = 0;
    }

    if(sim_time > 220*PERIOD && sim_time < 270*PERIOD) {
      dut->set_hour = 1;
    } else {
      dut->set_hour = 0;
    }

    if(sim_time % PERIOD == 0) {
	  	pos_edge_eval(dut);
	  	m_trace->dump(sim_time);
	  	neg_edge_eval(dut);
	  }

    if((sim_time % PERIOD) - 2 == 0) {
      neg_edge_eval(dut);
      m_trace->dump(sim_time);
      pos_edge_eval(dut);
    }

	  sim_time++;
  }

  dut->final();

  m_trace->close();
  delete dut;
}

void reset(ValarmTop* dut, int n) {
  if(sim_time < n) {
    dut->rstn = 0;
  } else {
    dut->rstn = 1;
  }
}

void neg_edge_eval(ValarmTop* dut) {
	dut->clk = 0;
	dut->eval();
}

void pos_edge_eval(ValarmTop* dut) {
	dut->clk = 1;
	dut->eval();
}
